<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1043828
-->
<head>
  <title>Basic test for Switching Keyboards.</title>
  <script type="application/javascript;version=1.7" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
  <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1043828">Mozilla Bug 1043828</a>
<p id="display"></p>
<pre id="test">
<script class="testbody" type="application/javascript;version=1.7">

SimpleTest.requestFlakyTimeout("untriaged");

inputmethod_setup(function() {
  runTest();
});

// The KB frame script running in Keyboard B.
function kbFrameScript() {
  function tryGetText() {
    var ctx = content.navigator.mozInputMethod.inputcontext;
    if (ctx) {
      var p = ctx.getText();
      p.then(function(){
        sendAsyncMessage('test:InputMethod:getText:Resolve');
      }, function(e){
        sendAsyncMessage('test:InputMethod:getText:Reject');
      });
    } else {
      dump("Could not get inputcontext") ;
    }
  }

  addMessageListener('test:InputMethod:getText:Do', function(){
    tryGetText();
  });
}

function runTest() {
  let app, keyboardA, keyboardB;
  let getTextPromise;
  let mmKeyboardA, mmKeyboardB;

  /**
   * Test flow:
   * 1. Create two keyboard iframes & a mozbrowser iframe with a text field in it & focus the text
   *    field.
   * 2. Set keyboard frame A as active input. Wait 200ms.
   * 3. Set keyboard frame B as active input. Wait 200ms.
   * 4. Set keyboard frame A as inactive. Wait 200ms.
   * 5. Allow frame b to use getText() with inputcontext to get the content from the text field
   *    iframe. Wait 200ms.
   * [Test would succeed if the Promise returned by getText() resolves correctly.
   *  Test would fail if otherwise]
   */

  let path = location.pathname;
  let basePath = location.protocol + '//' + location.host +
               path.substring(0, path.lastIndexOf('/'));

  const WAIT_TIME = 200;

  // STEP 1: Create the frames.
  function step1() {
    // app
    app = document.createElement('iframe');
    app.src = basePath + '/file_test_app.html';
    app.setAttribute('mozbrowser', true);
    document.body.appendChild(app);

    // keyboards
    keyboardA = document.createElement('iframe');
    keyboardA.setAttribute('mozbrowser', true);
    document.body.appendChild(keyboardA);

    keyboardB = document.createElement('iframe');
    keyboardB.setAttribute('mozbrowser', true);
    document.body.appendChild(keyboardB);

    // simulate two different keyboard apps
    let imeUrl = basePath + '/file_blank.html';

    keyboardA.src = imeUrl;
    keyboardB.src = imeUrl;

    var handler = {
      handleEvent: function(){
        keyboardB.removeEventListener('mozbrowserloadend', this);

        mmKeyboardB = SpecialPowers.getBrowserFrameMessageManager(keyboardB);

        mmKeyboardB.loadFrameScript('data:,(' + kbFrameScript.toString() + ')();', false);

        mmKeyboardB.addMessageListener('test:InputMethod:getText:Resolve', function() {
          info('getText() was resolved');
          inputmethod_cleanup();
        });

        mmKeyboardB.addMessageListener('test:InputMethod:getText:Reject', function() {
          ok(false, 'getText() was rejected');
          inputmethod_cleanup();
        });

        setTimeout(function(){
          step2();
        }, WAIT_TIME);
      }
    };

    keyboardB.addEventListener('mozbrowserloadend', handler);
  }

  // STEP 2: Set keyboard A active
  function step2() {
    info('step2');
    let req = keyboardA.setInputMethodActive(true);

    req.onsuccess = function(){
      setTimeout(function(){
        step3();
      }, WAIT_TIME);
    };

    req.onerror = function(){
      ok(false, 'setInputMethodActive failed: ' + this.error.name);
      inputmethod_cleanup();
    };
  }

  // STEP 3: Set keyboard B active
  function step3() {
    info('step3');
    let req = keyboardB.setInputMethodActive(true);

    req.onsuccess = function(){
      setTimeout(function(){
        step4();
      }, WAIT_TIME);
    };

    req.onerror = function(){
      ok(false, 'setInputMethodActive failed: ' + this.error.name);
      inputmethod_cleanup();
    };
  }

  // STEP 4: Set keyboard A inactive
  function step4() {
    info('step4');
    let req = keyboardA.setInputMethodActive(false);

    req.onsuccess = function(){
      setTimeout(function(){
        step5();
      }, WAIT_TIME);
    };

    req.onerror = function(){
      ok(false, 'setInputMethodActive failed: ' + this.error.name);
      inputmethod_cleanup();
    };
  }

  // STEP 5: getText
  function step5() {
    info('step5');
    mmKeyboardB.sendAsyncMessage('test:InputMethod:getText:Do');
  }

  step1();
}

</script>
</pre>
</body>
</html>

